#pragma once

#ifndef H264DECODE_H_
#define H264DECODE_H_

#include "TIOBuffer.h"

struct AVCodecContext;
struct AVCodec;
struct AVFrame;
struct SwsContext;
struct AVPicture;



typedef void (* H264VideoFrameCallback)(unsigned char* pBuf, int size,
                                         int width, int height, int fmt,
                                         void* pUser);

typedef void (* H264VideoDrawCallback)(HDC hdc, void* pUser);


class H264Decode
{
public:
    enum Constants
    {
        FRAME_FORMAT_RGB32 = 2,
        FRAME_FORMAT_YV12 = 3
    };

public:
    H264Decode();
    ~H264Decode();

    static void startup();
    static void cleanup();

    bool open();

    void close();

    bool isOpen() const;

    bool setVideoWnd(HWND hwnd);

    bool inputData(const unsigned char* buffer, size_t length);

    bool snap(const char* filename);

    bool getPictureSize(int& width, int& height);

    void refresh();

    int getPlayedFrame();

    
    void setDecodeCallback(H264VideoFrameCallback cb, void* pUser);

    void setDrawCallback(H264VideoDrawCallback cb, void* pUser);

    bool subclass();
    void cancelSubclass();

    LRESULT winProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    void onPaint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

private:
    void updateResolution();
    void closeScaleContext();

    void drawFrame();

    bool hasDecodeCallback();

    void doDecCallback();

    void doDrawCallback(HDC hdc);
    
private:
    HWND    m_hwnd;
    AVCodecContext* m_pContext;
    AVCodec*    m_pCodec;
    AVFrame*    m_pFrame;

    SwsContext* m_pScaleContext;
    int m_wndWidth;
    int m_wndHeight;

    AVPicture*  m_pPicture;
    BITMAPINFO  m_bmpInfo;
    
    int m_frameCount;

    comn::IOBuffer  m_decBuffer;
    
    H264VideoFrameCallback m_decCallback;
    void*   m_pDecUser;

    H264VideoDrawCallback   m_drawCallback;
    void*   m_pDrawUser;

    WNDPROC m_oldProc;
    

};


#endif //H264DECODE_H_